#include "dht11.h"
#if LARG_MEM
// Large: XDATA 内存模型
void Delay1us(void) //@24.000MHz
{
#if 1
    unsigned char data i;

    i = 2;
    while (--i);
#else
    NOP5();
#endif
}
#else
// Large: XDATA 内存模型
void Delay1us(void) //@24.000MHz
{
#if 1
    unsigned char data i;

    i = 3;
    while (--i);
#else
    NOP10();
#endif
}
#endif
void dht11_gpio_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;        // 结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_6;       // 指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;      // 指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P4, &GPIO_InitStructure); // 初始化
}

char DHT11_get_humidity_temperature(int *humidity, float *temperature)
{
    u16 cnt;   // 计数器
    u8 dat[5]; // 5个字节的数据， 5个8位，40个位
    u8 i, j;   // 循环变量
    float temp;

    // 1. 起始信号 拉低  18~30ms
    DHT = 0;
    delay_ms(20);
    DHT = 1;
    // 2. 主机释放总时间 10us ~ 35us
    cnt = 0;
    do {
        Delay1us(); // 1us
        cnt++;
        // 只有这个地方需要判断DHT11是否坏了
    } while (DHT == 1 && cnt < 50); // 如果50次都是1，说明DHT11没有响应，直接返回

    if (cnt < 10 || cnt > 35) {
        printf("%s err: %d\n", "主机释放总时间", (int)cnt);
        return -1; // 提前结束函数
    }

    // 3. 响应低电平时间 78us ~ 88us
    cnt = 0;
    do {
        Delay1us(); // 1us
        cnt++;
    } while (DHT == 0);
    if (cnt < 78 || cnt > 88) {
        printf("%s err: %d\n", "响应低电平时间", (int)cnt);
        return -2; // 提前结束函数
    }
    // 4. 响应高电平时间 80us ~ 92us
    cnt = 0;
    do {
        Delay1us(); // 1us
        cnt++;
    } while (DHT == 1);
    if (cnt < 80 || cnt > 92) {
        printf("%s err: %d\n", "响应低电平时间", (int)cnt);
        return -3; // 提前结束函数
    }
    // printf("cnt = %d\n", (int)cnt);
    // 5. 收到主机起始信号后，传感器一次性从数据总线（SDA)串出40位数据，高位先出
    // 40位数据，1字节8位，需要5个字节
    for (i = 0; i < 5; i++) {     // i = 0, 1, 2, 3, 4   dat[0], dat[1], dat[2], dat[3], dat[4]
        for (j = 0; j < 8; j++) { // j = 0, 1, 2, 3, 4, 5, 6, 7
            // 5.1 信号低电平时间 50us ~ 58us  低
            cnt = 0;
            do {
                Delay1us(); // 1us
                cnt++;
            } while (DHT == 0);
            if (cnt < 30 || cnt > 58) {
                printf("%s err: %d\n", "数据低电平时间", (int)cnt);
                return -4; // 提前结束函数
            }
            // 5.2 真正的0、1数据 23us ~74 us  高
            // 信号0 高电平时间  23us ~ 27us
            // 信号1 高电平时间  68us ~ 74us
            cnt = 0;
            do {
                Delay1us(); // 1us
                cnt++;
            } while (DHT == 1);
            /*if (cnt >= 23 && cnt <= 27) { // 信号0
            }
            if (cnt >= 68 && cnt <= 74) { // 信号1
            }*/
            // dat[i] 左移1位，留一个位置放信号，默认是0
            dat[i] <<= 1;
            if (cnt >= 68) { // 信号1
                dat[i] |= 1;
            } // 不处理，默认是0
        }
    }
    // 6. 数据校验
    // 湿度高 8 位    湿度低 8 位        温度高 8 位    温度低 8 位    校验位
    // dat[0]          dat[1]            dat[2]         dat[3]     dat[4]
    // 6.1 校验位＝湿度高位+湿度低位+温度高位+温度低位
    if (dat[0] + dat[1] + dat[2] + dat[3] != dat[4]) {
        printf("校验失败\n");
        return -5;
    }
    // printf("校验成功\n");
    // 6.2 湿度高位为湿度整数部分数据，湿度低位为湿度小数部分数据，其中湿度小数部分为 0
    // printf("湿度：%d \n", (int)dat[0]); // 湿度
    // 6.3 温度高位为温度整数部分数据，温度低位为温度小数部分数据(1位小数点)
    // 且温度低位 Bit7 (最高位) 为 1 则表示负温度，否则为正温度
    temp = dat[2] + (dat[3] & 0x7F) * 0.1; // 温度
    if (dat[3] & 0x80) {                   // 温度为负
        temp = -temp;                      // 取反
    }
    // printf("温度：%.1f \n", temp); // 温度

    *humidity    = dat[0]; // 湿度
    *temperature = temp;   // 温度

    return 0;
}
void dht11_task() _task_ DHT11_TASK
{
    while (1) {
        /* code */
        int humidity;
        float temperature;
        char flag;
        u8 str[32];
        // printf("dht11_task\n");
        flag = DHT11_get_humidity_temperature(&humidity, &temperature);
        // printf("flag = %d\n", (int)flag);
        sprintf(str, "th:temp:%d:hum:%.1f", (int)temperature, (float)humidity);
        // PrintString1(str);
        PrintString2(str);
        os_wait2(K_TMO, 200); // 5ms * 2 = 10ms
        os_wait2(K_TMO, 200); // 5ms * 2 = 10ms
        os_wait2(K_TMO, 200); // 5ms * 2 = 10ms
        os_wait2(K_TMO, 200); // 5ms * 2 = 10ms
        os_wait2(K_TMO, 200); // 5ms * 2 = 10ms
    }
}